using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using Opc.Ua;
using Opc.Ua.Client;

namespace WIT.DAQ.Core.Protocols.Socket;

/// <summary>
/// OPCUA的结构体帮助类
/// </summary>
internal class StructHelper
{
	/// <summary>
	/// 向OMRON结构体写入数据（兼容简单类型和数组）
	/// </summary>
	/// <param name="session"></param>
	/// <param name="nodeIdStrings"></param>
	/// <param name="values"></param>
	/// <returns></returns>
	internal static bool WriteValues(Session session, List<string> nodeIdStrings, List<object> values)
	{
		PrepareData(session, nodeIdStrings, values, out var rootNodeIds, out var rootDataValues);
		return WriteNodesData(session, rootNodeIds, rootDataValues);
	}

	private static void PrepareData(Session session, List<string> nodeIdStrings, List<object> values, out List<NodeId> rootNodeIds, out List<DataValue> rootDataValues)
	{
		rootNodeIds = new List<NodeId>();
		rootDataValues = new List<DataValue>();
		Dictionary<string, Dictionary<string, object>> dictionary = PrepareNodeIdMap(nodeIdStrings, values);
		foreach (KeyValuePair<string, Dictionary<string, object>> item2 in dictionary)
		{
			string propertyName;
			int rootArrayIndex = IsArray(item2.Key, out propertyName);
			NodeId nodeId = new NodeId(propertyName);
			DataValue dataValue = session.ReadValue(nodeId);
			object value = TEMP_ModifyData(session, propertyName, rootArrayIndex, dataValue.Value, item2.Value);
			DataValue item = new DataValue(new Variant(value));
			rootNodeIds.Add(nodeId);
			rootDataValues.Add(item);
		}
	}

	private static Dictionary<string, Dictionary<string, object>> PrepareNodeIdMap(List<string> nodeIdStrings, List<object> values)
	{
		Dictionary<string, Dictionary<string, object>> dictionary = new Dictionary<string, Dictionary<string, object>>();
		for (int i = 0; i < nodeIdStrings.Count; i++)
		{
			SplitPrefixAndSuffix(nodeIdStrings[i], out var prefix, out var suffix);
			if (!dictionary.ContainsKey(prefix))
			{
				dictionary.Add(prefix, new Dictionary<string, object>());
			}
			Dictionary<string, object> dictionary2 = dictionary[prefix];
			if (!dictionary2.ContainsKey(suffix))
			{
				dictionary2.Add(suffix, values[i]);
			}
		}
		return dictionary;
	}

	private static object TEMP_ModifyData(Session session, string rootNodeIdString, int rootArrayIndex, object sourceValue, Dictionary<string, object> dic_PropertyWithValue)
	{
		if (sourceValue is ExtensionObject)
		{
			List<StructItem> structItems = GetStructItems(session, rootNodeIdString, sourceValue);
			foreach (KeyValuePair<string, object> item in dic_PropertyWithValue)
			{
				RecursiveSetData(item.Key, item.Value, ref structItems);
			}
			ExtensionObject extensionObject = sourceValue as ExtensionObject;
			extensionObject.Body = ConvertStructToBytes(structItems).ToArray();
		}
		else if (sourceValue is ExtensionObject[])
		{
			List<StructItem> structItems2 = GetStructItems(session, rootNodeIdString, sourceValue);
			ExtensionObject[] array = sourceValue as ExtensionObject[];
			List<List<StructItem>> list = (List<List<StructItem>>)structItems2[0].Value;
			List<StructItem> structItems3 = list[rootArrayIndex];
			foreach (KeyValuePair<string, object> item2 in dic_PropertyWithValue)
			{
				RecursiveSetData(item2.Key, item2.Value, ref structItems3);
				array[rootArrayIndex].Body = ConvertStructToBytes(structItems3).ToArray();
			}
		}
		else
		{
			if (!(sourceValue is Array))
			{
				object value = dic_PropertyWithValue[""];
				if (sourceValue.GetType().Name == typeof(DateTime).Name)
				{
					return Convert.ToDateTime(value);
				}
				return Convert.ChangeType(value, sourceValue.GetType());
			}
			Array array2 = sourceValue as Array;
			foreach (KeyValuePair<string, object> item3 in dic_PropertyWithValue)
			{
				object obj = null;
				obj = ((!(array2.GetValue(rootArrayIndex).GetType().Name == typeof(DateTime).Name)) ? Convert.ChangeType(item3.Value, array2.GetValue(rootArrayIndex).GetType()) : ((object)Convert.ToDateTime(item3.Value)));
				array2.SetValue(obj, rootArrayIndex);
			}
		}
		return sourceValue;
	}

	private static void RecursiveSetData(string nodeIdSuffix, object value, ref List<StructItem> structItems)
	{
		SplitPrefixAndSuffix(nodeIdSuffix, out var prefix, out nodeIdSuffix);
		if (string.IsNullOrEmpty(nodeIdSuffix))
		{
			TEMP_SetItemValue(structItems, prefix, value);
			return;
		}
		string propertyName;
		int num = IsArray(prefix, out propertyName);
		StructItem structItem = structItems.FirstOrDefault((StructItem t) => t.Name == propertyName);
		if (structItem != null)
		{
			if (num > -1)
			{
				List<StructItem> list = null;
				if (structItem.Value is IList)
				{
					List<List<StructItem>> list2 = (List<List<StructItem>>)structItem.Value;
					list = list2[num];
				}
				else
				{
					List<StructItem> list3 = (List<StructItem>)structItem.Value;
					list = (List<StructItem>)list3[num].Value;
				}
				RecursiveSetData(nodeIdSuffix, value, ref list);
			}
			else
			{
				List<StructItem> structItems2 = structItem.Value as List<StructItem>;
				RecursiveSetData(nodeIdSuffix, value, ref structItems2);
			}
			return;
		}
		throw new Exception("BadNodeIdUnknown");
	}

	private static void TEMP_SetItemValue(List<StructItem> structItems, string nodeIdString, object value)
	{
		string propertyName;
		int index = IsArray(nodeIdString, out propertyName);
		StructItem structItem = structItems.FirstOrDefault((StructItem t) => t.Name == propertyName);
		if (structItem != null)
		{
			if (structItem.Value is IList)
			{
				(structItem.Value as List<object>)[index] = value;
			}
			else
			{
				structItem.Value = value;
			}
			return;
		}
		throw new Exception("BadNodeIdUnknown");
	}

	/// <summary>
	/// 以第1个分隔符分隔前后两部分
	/// </summary>
	/// <param name="content">被分隔的字符串</param>
	/// <param name="prefix">前缀</param>
	/// <param name="suffix">后缀</param>
	private static void SplitPrefixAndSuffix(string content, out string prefix, out string suffix)
	{
		prefix = string.Empty;
		suffix = string.Empty;
		if (content.Contains("."))
		{
			prefix = content.Substring(0, content.IndexOf("."));
			suffix = content.Substring(content.IndexOf(".") + 1);
		}
		else
		{
			prefix = content;
		}
	}

	/// <summary>
	/// 判断NodeId是否为数组
	/// </summary>
	/// <param name="content"></param>
	/// <param name="propertyName"></param>
	/// <returns></returns>
	internal static int IsArray(string content, out string propertyName)
	{
		Regex regex = new Regex("(.*?)\\[(.*?)\\]");
		if (regex.IsMatch(content))
		{
			Match match = regex.Match(content);
			propertyName = match.Result("$1");
			return Convert.ToInt32(match.Result("$2"));
		}
		propertyName = content;
		return -1;
	}

	private static bool WriteNodesData(Session session, List<NodeId> nodeIds, List<DataValue> values)
	{
		bool flag = false;
		WriteValueCollection writeValueCollection = new WriteValueCollection();
		for (int i = 0; i < nodeIds.Count; i++)
		{
			writeValueCollection.Add(new WriteValue
			{
				NodeId = nodeIds[i],
				Value = values[i],
				AttributeId = 13u
			});
		}
		session.Write(null, writeValueCollection, out var results, out var _);
		flag = !results.Any((StatusCode t) => StatusCode.IsNotGood(t));
		if (!flag)
		{
			throw new Exception(results.First((StatusCode t) => StatusCode.IsNotGood(t)).ToString());
		}
		return flag;
	}

	/// <summary>
	/// 获取结构体
	/// </summary>
	/// <param name="session"></param>
	/// <param name="nodeId"></param>
	/// <param name="value"></param>
	/// <returns></returns>
	internal static List<StructItem> GetStructItems(Session session, string nodeId, object value)
	{
		List<StructItem> list = new List<StructItem>();
		string parseString;
		string typeDictionary = GetTypeDictionary(nodeId, session, out parseString);
		List<object> varList = ParseTypeDictionary(typeDictionary, parseString);
		if (value is ExtensionObject)
		{
			ExtensionObject extensionObject = value as ExtensionObject;
			byte[] bytes = (byte[])extensionObject.Body;
			int index = 0;
			return ConvertToStructItems(typeDictionary, varList, bytes, ref index);
		}
		if (value is ExtensionObject[])
		{
			StructItem structItem = new StructItem();
			List<StructItem> list2 = new List<StructItem>();
			List<List<StructItem>> list3 = new List<List<StructItem>>();
			ExtensionObject[] array = value as ExtensionObject[];
			for (int i = 0; i < array.Length; i++)
			{
				byte[] bytes2 = (byte[])array[i].Body;
				int index2 = 0;
				list2 = ConvertToStructItems(typeDictionary, varList, bytes2, ref index2);
				list3.Add(list2);
			}
			structItem.Value = list3;
			list.Add(structItem);
		}
		return list;
	}

	private static List<StructItem> ConvertToStructItems(string xmlString, List<object> varList, byte[] bytes, ref int index)
	{
		List<StructItem> list = new List<StructItem>();
		foreach (object var in varList)
		{
			string name = ((string[])var)[0];
			string text = ((string[])var)[1];
			string value = ((string[])var)[2];
			StructItem structItem = new StructItem
			{
				Name = name
			};
			if (text == typeof(bool).Name)
			{
				if (string.IsNullOrEmpty(value))
				{
					structItem.DataType = typeof(bool);
					structItem.Value = BitConverter.ToBoolean(bytes, index);
					index++;
				}
				else
				{
					structItem.DataType = typeof(List<bool>);
					int num = Convert.ToInt32(list[list.Count - 1].Value);
					List<object> list2 = new List<object>();
					for (int i = 0; i < num; i++)
					{
						list2.Add(BitConverter.ToBoolean(bytes, index));
						index++;
					}
					structItem.Value = list2;
				}
			}
			else if (text == typeof(short).Name)
			{
				if (string.IsNullOrEmpty(value))
				{
					structItem.DataType = typeof(short);
					structItem.Value = BitConverter.ToInt16(bytes, index);
					index += 2;
				}
				else
				{
					structItem.DataType = typeof(List<short>);
					int num2 = Convert.ToInt32(list[list.Count - 1].Value);
					List<object> list3 = new List<object>();
					for (int j = 0; j < num2; j++)
					{
						list3.Add(BitConverter.ToInt16(bytes, index));
						index += 2;
					}
					structItem.Value = list3;
				}
			}
			else if (text == typeof(int).Name)
			{
				if (string.IsNullOrEmpty(value))
				{
					structItem.DataType = typeof(int);
					structItem.Value = BitConverter.ToInt32(bytes, index);
					index += 4;
				}
				else
				{
					structItem.DataType = typeof(List<int>);
					int num3 = Convert.ToInt32(list[list.Count - 1].Value);
					List<object> list4 = new List<object>();
					for (int k = 0; k < num3; k++)
					{
						list4.Add(BitConverter.ToInt32(bytes, index));
						index += 4;
					}
					structItem.Value = list4;
				}
			}
			else if (text == typeof(long).Name)
			{
				if (string.IsNullOrEmpty(value))
				{
					structItem.DataType = typeof(long);
					structItem.Value = BitConverter.ToInt64(bytes, index);
					index += 8;
				}
				else
				{
					structItem.DataType = typeof(List<long>);
					int num4 = Convert.ToInt32(list[list.Count - 1].Value);
					List<object> list5 = new List<object>();
					for (int l = 0; l < num4; l++)
					{
						list5.Add(BitConverter.ToInt64(bytes, index));
						index += 8;
					}
					structItem.Value = list5;
				}
			}
			else if (text == typeof(ushort).Name)
			{
				if (string.IsNullOrEmpty(value))
				{
					structItem.DataType = typeof(ushort);
					structItem.Value = BitConverter.ToUInt16(bytes, index);
					index += 2;
				}
				else
				{
					structItem.DataType = typeof(List<ushort>);
					int num5 = Convert.ToInt32(list[list.Count - 1].Value);
					List<object> list6 = new List<object>();
					for (int m = 0; m < num5; m++)
					{
						list6.Add(BitConverter.ToUInt16(bytes, index));
						index += 2;
					}
					structItem.Value = list6;
				}
			}
			else if (text == typeof(uint).Name)
			{
				if (string.IsNullOrEmpty(value))
				{
					structItem.DataType = typeof(uint);
					structItem.Value = BitConverter.ToUInt32(bytes, index);
					index += 4;
				}
				else
				{
					structItem.DataType = typeof(List<uint>);
					int num6 = Convert.ToInt32(list[list.Count - 1].Value);
					List<object> list7 = new List<object>();
					for (int n = 0; n < num6; n++)
					{
						list7.Add(BitConverter.ToUInt32(bytes, index));
						index += 4;
					}
					structItem.Value = list7;
				}
			}
			else if (text == typeof(ulong).Name)
			{
				if (string.IsNullOrEmpty(value))
				{
					structItem.DataType = typeof(ulong);
					structItem.Value = BitConverter.ToUInt64(bytes, index);
					index += 8;
				}
				else
				{
					structItem.DataType = typeof(List<ulong>);
					int num7 = Convert.ToInt32(list[list.Count - 1].Value);
					List<object> list8 = new List<object>();
					for (int num8 = 0; num8 < num7; num8++)
					{
						list8.Add(BitConverter.ToUInt64(bytes, index));
						index += 8;
					}
					structItem.Value = list8;
				}
			}
			else if (text == typeof(byte).Name)
			{
				if (string.IsNullOrEmpty(value))
				{
					structItem.DataType = typeof(byte);
					structItem.Value = bytes[index];
					index++;
				}
				else
				{
					int num9 = Convert.ToInt32(list[list.Count - 1].Value);
					List<object> list9 = new List<object>();
					for (int num10 = 0; num10 < num9; num10++)
					{
						list9.Add(bytes[index]);
						index++;
					}
					try
					{
						if (list9.Count % 8 != 0)
						{
							throw new Exception();
						}
						byte[] array = list9.Select((object t) => Convert.ToByte(t)).ToArray();
						if (array.Length == 8)
						{
							structItem.Value = DateTime.ParseExact(BitConverter.ToString(array).Replace("-", ""), "yyMMddHHmmssffff", CultureInfo.InvariantCulture);
							structItem.DataType = typeof(DateTime);
						}
						else
						{
							List<DateTime> list10 = new List<DateTime>();
							for (int num11 = 0; num11 < array.Length / 8; num11++)
							{
								byte[] array2 = new byte[8];
								for (int num12 = 0; num12 < 8; num12++)
								{
									array2[num12] = array[num11 * 8 + num12];
								}
								list10.Add(DateTime.ParseExact(BitConverter.ToString(array2).Replace("-", ""), "yyMMddHHmmssffff", CultureInfo.InvariantCulture));
							}
							structItem.Value = list10;
							structItem.DataType = typeof(List<DateTime>);
						}
					}
					catch
					{
						structItem.DataType = typeof(List<byte>);
						structItem.Value = list9;
					}
				}
			}
			else if (text == typeof(float).Name || text == "Float")
			{
				if (string.IsNullOrEmpty(value))
				{
					structItem.DataType = typeof(float);
					structItem.Value = BitConverter.ToSingle(bytes, index);
					index += 4;
				}
				else
				{
					structItem.DataType = typeof(List<float>);
					int num13 = Convert.ToInt32(list[list.Count - 1].Value);
					List<object> list11 = new List<object>();
					for (int num14 = 0; num14 < num13; num14++)
					{
						list11.Add(BitConverter.ToSingle(bytes, index));
						index += 4;
					}
					structItem.Value = list11;
				}
			}
			else if (text == typeof(double).Name)
			{
				if (string.IsNullOrEmpty(value))
				{
					structItem.DataType = typeof(double);
					structItem.Value = BitConverter.ToDouble(bytes, index);
					index += 8;
				}
				else
				{
					structItem.DataType = typeof(List<double>);
					int num15 = Convert.ToInt32(list[list.Count - 1].Value);
					List<object> list12 = new List<object>();
					for (int num16 = 0; num16 < num15; num16++)
					{
						list12.Add(BitConverter.ToDouble(bytes, index));
						index += 8;
					}
					structItem.Value = list12;
				}
			}
			else if (text == typeof(DateTime).Name)
			{
				if (string.IsNullOrEmpty(value))
				{
					structItem.DataType = typeof(DateTime);
					byte[] array3 = new byte[8];
					Array.Copy(bytes, index, array3, 0, 8);
					structItem.Value = DateTime.FromBinary(BitConverter.ToInt64(array3, 0)).AddHours(8.0).AddYears(1600)
						.ToString("yyyy-MM-dd HH:mm:ss.fff");
					index += 8;
				}
				else
				{
					structItem.DataType = typeof(List<DateTime>);
					int num17 = Convert.ToInt32(list[list.Count - 1].Value);
					List<object> list13 = new List<object>();
					for (int num18 = 0; num18 < num17; num18++)
					{
						byte[] array4 = new byte[8];
						Array.Copy(bytes, index, array4, 0, 8);
						list13.Add(DateTime.FromBinary(BitConverter.ToInt64(array4, 0)).AddHours(8.0).AddYears(1600)
							.ToString("yyyy-MM-dd HH:mm:ss.fff"));
						index += 8;
					}
					structItem.Value = list13;
				}
			}
			else if (text == typeof(string).Name || text == "CharArray")
			{
				if (string.IsNullOrEmpty(value))
				{
					structItem.DataType = typeof(string);
					int num19 = BitConverter.ToInt32(bytes, index);
					index += 4;
					if (num19 > 0)
					{
						structItem.Value = Encoding.UTF8.GetString(bytes, index, num19);
						index += num19;
					}
					else
					{
						structItem.Value = string.Empty;
					}
				}
				else
				{
					structItem.DataType = typeof(List<string>);
					int num20 = Convert.ToInt32(list[list.Count - 1].Value);
					List<object> list14 = new List<object>();
					for (int num21 = 0; num21 < num20; num21++)
					{
						int num22 = BitConverter.ToInt32(bytes, index);
						index += 4;
						if (num22 > 0)
						{
							list14.Add(Encoding.UTF8.GetString(bytes, index, num22));
							index += num22;
						}
						else
						{
							list14.Add(string.Empty);
						}
					}
					structItem.Value = list14;
				}
			}
			else if (text.Contains("STRUCT/UDT:") && string.IsNullOrEmpty(value))
			{
				structItem.DataType = typeof(object);
				string stringToParserFor = text.Remove(0, 11);
				List<object> varList2 = ParseTypeDictionary(xmlString, stringToParserFor);
				structItem.Value = ConvertToStructItems(xmlString, varList2, bytes, ref index);
			}
			else
			{
				if (!text.Contains("STRUCT/UDT:") || string.IsNullOrEmpty(value))
				{
					throw new Exception("通过OPCUA协议获取结构体数据时发现未知的数据类型名称[" + text + "]");
				}
				structItem.DataType = typeof(List<object>);
				string stringToParserFor2 = text.Remove(0, 11);
				int num23 = Convert.ToInt32(list[list.Count - 1].Value);
				List<List<StructItem>> list15 = new List<List<StructItem>>();
				for (int num24 = 0; num24 < num23; num24++)
				{
					List<object> varList3 = ParseTypeDictionary(xmlString, stringToParserFor2);
					list15.Add(ConvertToStructItems(xmlString, varList3, bytes, ref index));
				}
				structItem.Value = list15;
			}
			if (!string.IsNullOrEmpty(value))
			{
				list.RemoveAt(list.Count - 1);
			}
			list.Add(structItem);
		}
		return list;
	}

	/// <summary>Browses for the desired type dictonary to parse for containing data types</summary>
	/// <param name="nodeIdString">The node Id string</param>
	/// <param name="theSessionToBrowseIn">The current session to browse in</param>
	/// <param name="parseString">The name of the var to parse for inside of dictionary</param>
	/// <returns>The dictionary as ASCII string</returns>
	/// <exception cref="T:System.Exception">Throws and forwards any exception with short error description.</exception>
	private static string GetTypeDictionary(string nodeIdString, Session theSessionToBrowseIn, out string parseString)
	{
		Node node = theSessionToBrowseIn.ReadNode(nodeIdString);
		if (node.NodeClass == NodeClass.Variable)
		{
			VariableNode variableNode = (VariableNode)node.DataLock;
			NodeId nodeToBrowse = new NodeId(variableNode.DataType.Identifier, variableNode.DataType.NamespaceIndex);
			theSessionToBrowseIn.Browse(null, null, nodeToBrowse, 0u, BrowseDirection.Forward, ReferenceTypeIds.HasEncoding, includeSubtypes: true, 0u, out var continuationPoint, out var references);
			if (references.Count == 0)
			{
				Exception ex = new Exception("No data type to encode. Could be a build-in data type you want to read.");
				throw ex;
			}
			foreach (ReferenceDescription item in references)
			{
				if (item.DisplayName.Text == "Default Binary")
				{
					nodeToBrowse = new NodeId(item.NodeId.Identifier, item.NodeId.NamespaceIndex);
					continue;
				}
				Exception ex2 = new Exception("No default binary data type found.");
				throw ex2;
			}
			references = null;
			theSessionToBrowseIn.Browse(null, null, nodeToBrowse, 0u, BrowseDirection.Forward, ReferenceTypeIds.HasDescription, includeSubtypes: true, 0u, out continuationPoint, out references);
			if (references.Count == 0)
			{
				Exception ex3 = new Exception("No data type description found in address space.");
				throw ex3;
			}
			nodeToBrowse = new NodeId(references[0].NodeId.Identifier, references[0].NodeId.NamespaceIndex);
			DataValue dataValue = theSessionToBrowseIn.ReadValue(nodeToBrowse);
			parseString = dataValue.Value.ToString();
			references = null;
			theSessionToBrowseIn.Browse(null, null, nodeToBrowse, 0u, BrowseDirection.Inverse, ReferenceTypeIds.HasComponent, includeSubtypes: true, 0u, out continuationPoint, out references);
			if (references.Count == 0)
			{
				Exception ex4 = new Exception("Data type isn't a component of parent type in address space. Can't continue decoding.");
				throw ex4;
			}
			nodeToBrowse = new NodeId(references[0].NodeId.Identifier, references[0].NodeId.NamespaceIndex);
			dataValue = theSessionToBrowseIn.ReadValue(nodeToBrowse);
			return Encoding.UTF8.GetString((byte[])dataValue.Value);
		}
		Exception ex5 = new Exception("No variable data type found");
		throw ex5;
	}

	/// <summary>
	/// Parse xmlString to create objects of the struct/UDT containing var name and var data type
	/// </summary>
	/// <param name="xmlStringToParse"></param>
	/// <param name="stringToParserFor"></param>
	/// <returns></returns>
	private static List<object> ParseTypeDictionary(string xmlStringToParse, string stringToParserFor)
	{
		List<object> list = new List<object>();
		xmlStringToParse = xmlStringToParse.Remove(xmlStringToParse.Length - 1);
		XmlDocument xmlDocument = new XmlDocument();
		xmlDocument.LoadXml(xmlStringToParse);
		xmlDocument.GetElementsByTagName(stringToParserFor);
		XmlNodeList elementsByTagName = xmlDocument.GetElementsByTagName("opc:StructuredType");
		XmlNode xmlNode = null;
		foreach (XmlNode item in elementsByTagName)
		{
			if (item.Attributes["Name"].Value == stringToParserFor)
			{
				xmlNode = item;
				break;
			}
		}
		if (xmlNode == null)
		{
			return null;
		}
		foreach (XmlNode childNode in xmlNode.ChildNodes)
		{
			string[] array = new string[3]
			{
				childNode.Attributes["Name"].Value,
				childNode.Attributes["TypeName"].Value,
				null
			};
			if (childNode.Attributes["LengthField"] != null)
			{
				array[2] = childNode.Attributes["LengthField"].Value;
			}
			else
			{
				array[2] = "";
			}
			if (!array[1].Contains("tns:"))
			{
				array[1] = array[1].Remove(0, 4);
			}
			else
			{
				array[1] = array[1].Remove(0, 4);
				array[1] = array[1].Insert(0, "STRUCT/UDT:");
			}
			list.Add(array);
		}
		return list;
	}

	private static List<byte> ConvertStructToBytes(List<StructItem> dataToWrite)
	{
		List<byte> list = new List<byte>();
		foreach (StructItem item2 in dataToWrite)
		{
			if (item2.DataType == typeof(bool))
			{
				bool value = Convert.ToBoolean(item2.Value);
				list.Add(Convert.ToByte(value));
				continue;
			}
			if (item2.DataType == typeof(List<bool>))
			{
				List<object> list2 = item2.Value as List<object>;
				byte[] bytes = BitConverter.GetBytes(list2.Count);
				list.AddRange(bytes);
				foreach (object item3 in list2)
				{
					bool value2 = Convert.ToBoolean(item3);
					list.Add(Convert.ToByte(value2));
				}
				continue;
			}
			if (item2.DataType == typeof(short))
			{
				byte[] bytes2 = BitConverter.GetBytes(Convert.ToInt16(item2.Value));
				list.AddRange(bytes2);
				continue;
			}
			if (item2.DataType == typeof(List<short>))
			{
				List<object> list3 = item2.Value as List<object>;
				byte[] bytes3 = BitConverter.GetBytes(list3.Count);
				list.AddRange(bytes3);
				foreach (object item4 in list3)
				{
					byte[] bytes4 = BitConverter.GetBytes(Convert.ToInt16(item4));
					list.AddRange(bytes4);
				}
				continue;
			}
			if (item2.DataType == typeof(int))
			{
				byte[] bytes5 = BitConverter.GetBytes(Convert.ToInt32(item2.Value));
				list.AddRange(bytes5);
				continue;
			}
			if (item2.DataType == typeof(List<int>))
			{
				List<object> list4 = item2.Value as List<object>;
				byte[] bytes6 = BitConverter.GetBytes(list4.Count);
				list.AddRange(bytes6);
				foreach (object item5 in list4)
				{
					byte[] bytes7 = BitConverter.GetBytes(Convert.ToInt32(item5));
					list.AddRange(bytes7);
				}
				continue;
			}
			if (item2.DataType == typeof(long))
			{
				byte[] bytes8 = BitConverter.GetBytes(Convert.ToInt64(item2.Value));
				list.AddRange(bytes8);
				continue;
			}
			if (item2.DataType == typeof(List<long>))
			{
				List<object> list5 = item2.Value as List<object>;
				byte[] bytes9 = BitConverter.GetBytes(list5.Count);
				list.AddRange(bytes9);
				foreach (object item6 in list5)
				{
					byte[] bytes10 = BitConverter.GetBytes(Convert.ToInt64(item6));
					list.AddRange(bytes10);
				}
				continue;
			}
			if (item2.DataType == typeof(ushort))
			{
				byte[] bytes11 = BitConverter.GetBytes(Convert.ToUInt16(item2.Value));
				list.AddRange(bytes11);
				continue;
			}
			if (item2.DataType == typeof(List<ushort>))
			{
				List<object> list6 = item2.Value as List<object>;
				byte[] bytes12 = BitConverter.GetBytes(list6.Count);
				list.AddRange(bytes12);
				foreach (object item7 in list6)
				{
					byte[] bytes13 = BitConverter.GetBytes(Convert.ToUInt16(item7));
					list.AddRange(bytes13);
				}
				continue;
			}
			if (item2.DataType == typeof(uint))
			{
				byte[] bytes14 = BitConverter.GetBytes(Convert.ToUInt32(item2.Value));
				list.AddRange(bytes14);
				continue;
			}
			if (item2.DataType == typeof(List<uint>))
			{
				List<object> list7 = item2.Value as List<object>;
				byte[] bytes15 = BitConverter.GetBytes(list7.Count);
				list.AddRange(bytes15);
				foreach (object item8 in list7)
				{
					byte[] bytes16 = BitConverter.GetBytes(Convert.ToUInt32(item8));
					list.AddRange(bytes16);
				}
				continue;
			}
			if (item2.DataType == typeof(ulong))
			{
				byte[] bytes17 = BitConverter.GetBytes(Convert.ToUInt64(item2.Value));
				list.AddRange(bytes17);
				continue;
			}
			if (item2.DataType == typeof(List<ulong>))
			{
				List<object> list8 = item2.Value as List<object>;
				byte[] bytes18 = BitConverter.GetBytes(list8.Count);
				list.AddRange(bytes18);
				foreach (object item9 in list8)
				{
					byte[] bytes19 = BitConverter.GetBytes(Convert.ToUInt64(item9));
					list.AddRange(bytes19);
				}
				continue;
			}
			if (item2.DataType == typeof(byte))
			{
				list.Add(Convert.ToByte(item2.Value));
				continue;
			}
			if (item2.DataType == typeof(List<byte>))
			{
				List<object> list9 = item2.Value as List<object>;
				byte[] bytes20 = BitConverter.GetBytes(list9.Count);
				list.AddRange(bytes20);
				foreach (object item10 in list9)
				{
					list.Add(Convert.ToByte(item10));
				}
				continue;
			}
			if (item2.DataType == typeof(float))
			{
				byte[] bytes21 = BitConverter.GetBytes(Convert.ToSingle(item2.Value));
				list.AddRange(bytes21);
				continue;
			}
			if (item2.DataType == typeof(List<float>))
			{
				List<object> list10 = item2.Value as List<object>;
				byte[] bytes22 = BitConverter.GetBytes(list10.Count);
				list.AddRange(bytes22);
				foreach (object item11 in list10)
				{
					byte[] bytes23 = BitConverter.GetBytes(Convert.ToSingle(item11));
					list.AddRange(bytes23);
				}
				continue;
			}
			if (item2.DataType == typeof(double))
			{
				byte[] bytes24 = BitConverter.GetBytes(Convert.ToDouble(item2.Value));
				list.AddRange(bytes24);
				continue;
			}
			if (item2.DataType == typeof(List<double>))
			{
				List<object> list11 = item2.Value as List<object>;
				byte[] bytes25 = BitConverter.GetBytes(list11.Count);
				list.AddRange(bytes25);
				foreach (object item12 in list11)
				{
					byte[] bytes26 = BitConverter.GetBytes(Convert.ToDouble(item12));
					list.AddRange(bytes26);
				}
				continue;
			}
			if (item2.DataType == typeof(DateTime))
			{
				byte[] bytes27 = BitConverter.GetBytes(Convert.ToDateTime(item2.Value).AddHours(-8.0).AddYears(-1600)
					.ToBinary());
				list.AddRange(bytes27);
				continue;
			}
			if (item2.DataType == typeof(List<DateTime>))
			{
				List<object> list12 = item2.Value as List<object>;
				byte[] bytes28 = BitConverter.GetBytes(list12.Count);
				list.AddRange(bytes28);
				foreach (object item13 in list12)
				{
					byte[] bytes29 = BitConverter.GetBytes(Convert.ToDateTime(item2.Value).AddHours(-8.0).AddYears(-1600)
						.ToBinary());
					list.AddRange(bytes29);
				}
				continue;
			}
			if (item2.DataType == typeof(string))
			{
				byte[] bytes30 = Encoding.UTF8.GetBytes(item2.Value.ToString());
				byte[] bytes31 = BitConverter.GetBytes(bytes30.Length);
				list.AddRange(bytes31);
				byte[] array = bytes30;
				foreach (byte item in array)
				{
					list.Add(item);
				}
				continue;
			}
			if (item2.DataType == typeof(List<string>))
			{
				List<object> list13 = item2.Value as List<object>;
				byte[] bytes32 = BitConverter.GetBytes(list13.Count);
				list.AddRange(bytes32);
				foreach (object item14 in list13)
				{
					byte[] bytes33 = BitConverter.GetBytes(item14.ToString().Length);
					list.AddRange(bytes33);
					char[] array2 = item14.ToString().ToCharArray();
					foreach (char value3 in array2)
					{
						list.Add(Convert.ToByte(value3));
					}
				}
				continue;
			}
			if (item2.DataType == typeof(object))
			{
				List<StructItem> dataToWrite2 = item2.Value as List<StructItem>;
				list.InsertRange(list.Count, ConvertStructToBytes(dataToWrite2));
				continue;
			}
			if (item2.DataType == typeof(List<object>))
			{
				List<List<StructItem>> list14 = item2.Value as List<List<StructItem>>;
				byte[] bytes34 = BitConverter.GetBytes(list14.Count);
				list.AddRange(bytes34);
				foreach (List<StructItem> item15 in list14)
				{
					list.InsertRange(list.Count, ConvertStructToBytes(item15));
				}
				continue;
			}
			Exception ex = new Exception("Can't covert " + item2.Name + ".");
			throw ex;
		}
		return list;
	}
}
